package ru.mipt.sport.gui;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import ru.mipt.sport.gui.competition.CreateCompetitionWizard;
import ru.mipt.sport.gui.competition.EditCompetitionRunDialog;
import ru.mipt.sport.gui.registry.InstitutionsWindow;
import ru.mipt.sport.gui.registry.PeopleRegistryWindow;
import ru.mipt.sport.gui.registry.SportsWindow;
import ru.mipt.sport.gui.reports.FinalizeStageDialog;
import ru.mipt.sport.model.interfaces.Competition;
import ru.mipt.sport.model.interfaces.CompetitionRun;
import ru.mipt.sport.model.interfaces.CompetitionSport;
import ru.mipt.sport.model.interfaces.CompetitionStage;
import ru.mipt.sport.utils.DBHelper;
import ru.mipt.sport.utils.DBUtils;

/**
 *
 * @author Danon
 */
public class MainWindow extends javax.swing.JFrame {
    
    private final DBUtils db = DBUtils.getInstance();

    /**
     * Creates new form MainWindow
     */
    public MainWindow() {
        initComponents();
        populateCompetitionTree();
        if(competitionsTree.getRowCount()>0)
            competitionsTree.expandRow(0);
    }
    
    
    private void populateCompetitionTree() {
        DefaultTreeModel model = (DefaultTreeModel)competitionsTree.getModel();
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Competitions", true);
        model.setRoot(root);
        try {
            EntityManager em = db.getEntityManager();
            Query q = em.createQuery("select c from CompetitionEntity c", Competition.class);
            List<Competition> list = q.getResultList();
            if(list == null)
                return;
            for(Competition c : list) {
                addCompetition(root, c);
            }
        } catch (Exception ex) {
            System.err.println("Failed to fetch competition list!");
            System.err.println("Exception: "+ex);
        }
    }
    
    private void addCompetition(DefaultMutableTreeNode root, Competition competition) {
        DefaultMutableTreeNode cNode = new DefaultMutableTreeNode(competition);
        try {
            EntityManager em = db.getEntityManager();
            Query q = em.createQuery("select s from CompetitionSportEntity s where s.competition = :competition", Competition.class);
            q.setParameter("competition", competition);
            List<CompetitionSport> list = q.getResultList();
            if(list == null)
                return;
            for(CompetitionSport s : list) {
                addCompetitionSport(cNode, s);
            }
        } catch (Exception ex) {
            System.err.println("Failed to fetch competition sports list!");
            System.err.println("Exception: "+ex);
        }
        
        root.add(cNode);
    }
    
    private void addCompetitionSport(DefaultMutableTreeNode parent, CompetitionSport sport) {
        DefaultMutableTreeNode sNode = new DefaultMutableTreeNode(sport);
        try {
             EntityManager em = db.getEntityManager();
             Query q = em.createQuery("select s from CompetitionStageEntity s where s.sport = :sport", CompetitionStage.class);
             List<CompetitionStage> list = q.setParameter("sport", sport).getResultList();
             if(list == null)
                return;
             for(CompetitionStage stage : list) {
                 addCompetitionStage(sNode, stage);
             }
        } catch (Exception ex) {
            System.err.println("Failed to fetch sport stages list!");
            System.err.println("Exception: "+ex);
        }
        parent.add(sNode);
    }
    
    private void addCompetitionStage(DefaultMutableTreeNode parent, CompetitionStage stage) {
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(stage);
        try {
             EntityManager em = db.getEntityManager();
             Query q = em.createQuery("select r from CompetitionRunEntity r where r.stage = :stage", CompetitionRun.class);
             List<CompetitionRun> list = q.setParameter("stage", stage).getResultList();
             if(list == null)
                return;
             for(CompetitionRun run : list) {
                 node.add(new DefaultMutableTreeNode(run, false));
             }
        } catch (Exception ex) {
            System.err.println("Failed to fetch sport stages list!");
            System.err.println("Exception: "+ex);
        }
        parent.add(node);
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        competitionsTreePM = new javax.swing.JPopupMenu();
        removeMenuItem = new javax.swing.JMenuItem();
        addRunMenuItem = new javax.swing.JMenuItem();
        finalizeStageMenuItem = new javax.swing.JMenuItem();
        topPanel = new javax.swing.JPanel();
        jToolBar1 = new javax.swing.JToolBar();
        leftPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        competitionsTree = new javax.swing.JTree();
        jLayeredPane1 = new javax.swing.JLayeredPane();
        mainMenuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        exitMenuItem = new javax.swing.JMenuItem();
        registryMenu = new javax.swing.JMenu();
        calendarMenuItem = new javax.swing.JMenuItem();
        peopleMenuItem = new javax.swing.JMenuItem();
        sportsMenuItem = new javax.swing.JMenuItem();
        institutionsMenuItem = new javax.swing.JMenuItem();
        competitionMenu = new javax.swing.JMenu();
        createCompetitionMenuItem = new javax.swing.JMenuItem();
        requestMenuItem = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        aboutMenuItem = new javax.swing.JMenuItem();

        removeMenuItem.setText("Remove element");
        removeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeMenuItemActionPerformed(evt);
            }
        });
        competitionsTreePM.add(removeMenuItem);

        addRunMenuItem.setText("Add run");
        addRunMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addRunMenuItemActionPerformed(evt);
            }
        });
        competitionsTreePM.add(addRunMenuItem);

        finalizeStageMenuItem.setText("Finalize stage...");
        finalizeStageMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                finalizeStageMenuItemActionPerformed(evt);
            }
        });
        competitionsTreePM.add(finalizeStageMenuItem);

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("MIPT :: Athletics");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                mainWindowClosed(evt);
            }
        });

        jToolBar1.setRollover(true);

        javax.swing.GroupLayout topPanelLayout = new javax.swing.GroupLayout(topPanel);
        topPanel.setLayout(topPanelLayout);
        topPanelLayout.setHorizontalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(topPanelLayout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 617, Short.MAX_VALUE))
        );
        topPanelLayout.setVerticalGroup(
            topPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        getContentPane().add(topPanel, java.awt.BorderLayout.PAGE_START);

        leftPanel.setPreferredSize(new java.awt.Dimension(400, 341));

        competitionsTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
        competitionsTree.setComponentPopupMenu(competitionsTreePM);
        competitionsTree.setShowsRootHandles(false);
        competitionsTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                competitionsTreeMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(competitionsTree);

        javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout(leftPanel);
        leftPanel.setLayout(leftPanelLayout);
        leftPanelLayout.setHorizontalGroup(
            leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(leftPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
                .addContainerGap())
        );
        leftPanelLayout.setVerticalGroup(
            leftPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, leftPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 406, Short.MAX_VALUE)
                .addContainerGap())
        );

        getContentPane().add(leftPanel, java.awt.BorderLayout.LINE_START);
        getContentPane().add(jLayeredPane1, java.awt.BorderLayout.CENTER);

        fileMenu.setText("File");

        exitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        mainMenuBar.add(fileMenu);

        registryMenu.setText("Registry");

        calendarMenuItem.setText("Calendar...");
        calendarMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                calendarMenuItemActionPerformed(evt);
            }
        });
        registryMenu.add(calendarMenuItem);

        peopleMenuItem.setText("People...");
        peopleMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                peopleMenuItemActionPerformed(evt);
            }
        });
        registryMenu.add(peopleMenuItem);

        sportsMenuItem.setText("Sports...");
        sportsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sportsMenuItemActionPerformed(evt);
            }
        });
        registryMenu.add(sportsMenuItem);

        institutionsMenuItem.setText("Institutions");
        institutionsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                institutionsMenuItemActionPerformed(evt);
            }
        });
        registryMenu.add(institutionsMenuItem);

        mainMenuBar.add(registryMenu);

        competitionMenu.setText("Competition");

        createCompetitionMenuItem.setText("Create competition...");
        createCompetitionMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createCompetitionMenuItemActionPerformed(evt);
            }
        });
        competitionMenu.add(createCompetitionMenuItem);

        requestMenuItem.setText("Add participant");
        requestMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                requestMenuItemActionPerformed(evt);
            }
        });
        competitionMenu.add(requestMenuItem);

        mainMenuBar.add(competitionMenu);

        helpMenu.setText("Help");

        aboutMenuItem.setText("About SportZ...");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(aboutMenuItem);

        mainMenuBar.add(helpMenu);

        setJMenuBar(mainMenuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        this.dispose();
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void mainWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_mainWindowClosed
        System.out.println("Main window closed");
        System.out.println("Good bye!");
        System.exit(0);
    }//GEN-LAST:event_mainWindowClosed

    private void requestMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_requestMenuItemActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_requestMenuItemActionPerformed

    private void institutionsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_institutionsMenuItemActionPerformed
        new InstitutionsWindow().setVisible(true);
    }//GEN-LAST:event_institutionsMenuItemActionPerformed

    private void sportsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sportsMenuItemActionPerformed
       new SportsWindow().setVisible(true);
    }//GEN-LAST:event_sportsMenuItemActionPerformed

    private void peopleMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_peopleMenuItemActionPerformed
        new PeopleRegistryWindow().setVisible(true);
    }//GEN-LAST:event_peopleMenuItemActionPerformed

    private void calendarMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_calendarMenuItemActionPerformed
        JOptionPane.showMessageDialog(rootPane, "Sorry. This feature is not implemented yet.", "Calendar...", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_calendarMenuItemActionPerformed

    private void createCompetitionMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createCompetitionMenuItemActionPerformed
        new CreateCompetitionWizard(this, true).setVisible(true);
        populateCompetitionTree();
        competitionsTree.treeDidChange();
    }//GEN-LAST:event_createCompetitionMenuItemActionPerformed

    private void removeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeMenuItemActionPerformed
        // remove competition
        if(competitionsTree.isSelectionEmpty())
            return; // nothing to remove
        TreePath path = competitionsTree.getSelectionPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
        Object o = node.getUserObject();
        
        // Competition ???
        if(o instanceof Competition) {
            System.out.println("Removing competition "+o+" ...");
            Competition c = (Competition)o;
            synchronized(db) {
                try {
                    DBHelper.getInstance().deleteCompetition(db, c);
                    db.commit();
                } catch (Exception ex) {
                    db.rollback();
                }
            }
        }
        
        // CompetitionSport ???
        if(o instanceof CompetitionSport) {
            System.out.println("Removing competition sport "+o+" ...");
            CompetitionSport s = (CompetitionSport)o;
            synchronized(db) {
                try {
                    DBHelper.getInstance().deleteCompetitionSport(db, s);
                    db.commit();
                } catch (Exception ex) {
                    db.rollback();
                }
            }
        }
        
        // CompetitionStage ???
        if(o instanceof CompetitionStage) {
            System.out.println("Removing competition stage "+o+" ...");
            CompetitionStage s = (CompetitionStage)o;
            synchronized(db) {
                try {
                    DBHelper.getInstance().deleteCompetitionStage(db, s);
                    db.commit();
                } catch (Exception ex) {
                    db.rollback();
                }
            }
        }
        
        // CompetitionRun ???
        if(o instanceof CompetitionRun) {
            System.out.println("Removing competition run "+o+" ...");
            CompetitionRun r = (CompetitionRun)o;
            synchronized(db) {
                try {
                    DBHelper.getInstance().deleteCompetitionRun(db, r);
                    db.commit();
                } catch (Exception ex) {
                    db.rollback();
                }
            }
        }
        
        //refresh tree
        populateCompetitionTree();
        competitionsTree.setSelectionPath(path);
        competitionsTree.treeDidChange();
        
    }//GEN-LAST:event_removeMenuItemActionPerformed

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        JOptionPane.showMessageDialog(rootPane, "SportZ - Organize competitions and other sports events\n"
                + "Developed by Anton Danshin (anton.danshin@frtk.ru). May 2012", "About SportZ", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void addRunMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addRunMenuItemActionPerformed
        if(competitionsTree.isSelectionEmpty())
            return; // nothing selected
        TreePath path = competitionsTree.getSelectionPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
        Object o = node.getUserObject();
        
        // CompetitionStage ???
        if(o instanceof CompetitionStage) {
            CompetitionStage s = (CompetitionStage)o;
            synchronized(db) {
                try {
                    CompetitionRun run = DBHelper.getInstance().createCompetitionRun(db, s);
                    if(run!=null) {
                        run.setIndex(node.getChildCount()+1);
                        
                        node.add(new DefaultMutableTreeNode(run));
                        db.commit();
                        // show dialog to edit run participants
                    }                
                } catch (Exception ex) {
                    db.rollback();
                }
            }
        }
        
        //refresh tree
        populateCompetitionTree();
        competitionsTree.setSelectionPath(path);
        competitionsTree.treeDidChange();
        
    }//GEN-LAST:event_addRunMenuItemActionPerformed

    private void competitionsTreeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_competitionsTreeMouseClicked
        if(evt!=null&&evt.getClickCount()<2)
            return;
        if(competitionsTree.isSelectionEmpty())
            return; // nothing selected
        TreePath path = competitionsTree.getSelectionPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
        Object o = node.getUserObject();
        
        // CompetitionRun ???
        if(o instanceof CompetitionRun) {
            CompetitionRun r = (CompetitionRun)o;
            EditCompetitionRunDialog dlg = new EditCompetitionRunDialog(this, true, r);
            dlg.setVisible(true);
        }
    }//GEN-LAST:event_competitionsTreeMouseClicked

    private void finalizeStageMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finalizeStageMenuItemActionPerformed
        // Finalize competition stage - show the final table of the stage with ranks, levels and points
        if(competitionsTree.isSelectionEmpty())
            return; // nothing selected
        TreePath path = competitionsTree.getSelectionPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
        Object o = node.getUserObject();
        
        // CompetitionStage ???
        if(o instanceof CompetitionStage) {
            CompetitionStage s = (CompetitionStage)o;
            FinalizeStageDialog dlg = new FinalizeStageDialog(this, true, s);
            dlg.setVisible(true);
        }
    }//GEN-LAST:event_finalizeStageMenuItemActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JMenuItem addRunMenuItem;
    private javax.swing.JMenuItem calendarMenuItem;
    private javax.swing.JMenu competitionMenu;
    private javax.swing.JTree competitionsTree;
    private javax.swing.JPopupMenu competitionsTreePM;
    private javax.swing.JMenuItem createCompetitionMenuItem;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenuItem finalizeStageMenuItem;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JMenuItem institutionsMenuItem;
    private javax.swing.JLayeredPane jLayeredPane1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JPanel leftPanel;
    private javax.swing.JMenuBar mainMenuBar;
    private javax.swing.JMenuItem peopleMenuItem;
    private javax.swing.JMenu registryMenu;
    private javax.swing.JMenuItem removeMenuItem;
    private javax.swing.JMenuItem requestMenuItem;
    private javax.swing.JMenuItem sportsMenuItem;
    private javax.swing.JPanel topPanel;
    // End of variables declaration//GEN-END:variables
}
